/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#pragma once

/// Omen Headers
#include "OmenConfig.h"
#include "IOmenObject.h"

#include <IOmenScene.h>
#include <IOmenCamera.h>
#include <IOmenModel.h>
#include <IOmenLightSource.h>

/// STL Headers
#include <vector>
#include <memory>

namespace Omen
{    
    class Scene : public IScene
    {
    #define GUID_OMEN_SCENE "6C927094-D198-4e45-915D-A112A1E93B37"

    public:
        OMEN_API virtual Omen_GUID classId() const { return OMEN_UUID(GUID_OMEN_SCENE); }    /// <summary>Defines the class ID</summary>

        OMEN_API Scene();
        OMEN_API virtual ~Scene();
        
        /// Scene merging
        OMEN_API virtual void            mergeScene( const IScene* pOtherScene );                                /// <summary>Add the contents of the given scene to this scene</summary>

        /// cameras
        OMEN_API virtual void            addCamera( const ICamera* pCamera );                                    /// <summary>Add a new camera to the scene</summary>
        OMEN_API virtual unsigned long   cameraCount() const;                                                    /// <summary>Returns the number of cameras in the scene</summary>
        OMEN_API virtual void            getCameras( ICamera** pListCameras, unsigned long maxListSize ) const;   /// <summary>Add a new camera to the scene</summary>
        OMEN_API virtual ICamera*        currentCamera() const;                                                  /// <summary>Return currently active camera</summary>
        OMEN_API virtual void            setCurrentCamera( const ICamera* pCamera )const;                        /// <summary>Sets the currently active camera</summary>
        OMEN_API virtual ICamera*        getCamera( unsigned long iCamera ) const;

        /// models
        OMEN_API virtual void            addModel( const IModel* pModel );                                       /// <summary>Add a new Model to the scene</summary>
        OMEN_API virtual void            getModels( IModel** pListModels, unsigned long maxListSize ) const;      /// <summary>Add a new Model to the scene</summary>
        OMEN_API virtual unsigned long   modelCount() const;                                                    /// <summary>Returns the number of models in the scene</summary>
        OMEN_API virtual IModel*         getModel( unsigned long iModel ) const;
        OMEN_API virtual IModel*         findModel( const std::wstring& modelName ) const;

        /// lights
        OMEN_API virtual void            addLight( const ILight* pLight );                                       /// <summary>Add a new Light to the scene</summary>
        OMEN_API virtual void            getLights( ILight** pListLights, unsigned long maxListSize ) const;      /// <summary>Add a new Light to the scene</summary>
        OMEN_API virtual unsigned long   lightCount() const;                                                    /// <summary>Returns the number of lights in the scene</summary>
        OMEN_API virtual ILight*         getLight( unsigned long iCamera ) const;

        /// Octree
        OMEN_API Omen::IOctree*          createOctree( unsigned int maximumDepth, unsigned int minimumFaceCount ); /// <summary>Create octree for this scene</summary>
        OMEN_API virtual void            setOctree( IOctree* pOctree );                                    /// <summary>Set the current octree representing the current model in 3d-space</summary>
        OMEN_API virtual Omen::IOctree*  octree() const;                                                         /// <summary>Returns the current octree</summary>

        /// rendering interface
        OMEN_API virtual void            render( const IRenderer* pRenderer) const;                              /// <summary>Render this scene using given renderer</summary>

        /// collision detection
        virtual void                     checkCollisions();

        // copy assign operator
        OMEN_API Omen::Scene& operator=( const Omen::Scene& );

    protected:
    private:
        bool reallocPtrs();            /// <summary>Reallocate the pointers for models and lights to be transfered to the renderer</summary>

    private:
        int            m_modelCount;
        int            m_cameraCount;
        int            m_lightCount;

        mutable Omen::ICamera*    m_pCurrentCamera;

        
        std::vector<Omen::IModel*>    m_models;
        std::vector<Omen::ICamera*>   m_cameras;
        std::vector<Omen::ILight*>    m_lights;

        Omen::IModel**                  m_pModelPtrs;
        Omen::ILight**                  m_pLightPtrs;

        Omen::IOctree*                  m_pOctree;
    };
}